The engine uses p.alerts.cnt as an index to access the packet alert that
has the `pass` action for the verdict.
For IDS/IPS mode, a `pass` will always be the last signature in the
alert queue. However, that position could be either `p.alerts.cnt` or
`p.alerts.cnt-1`, depending on whether the `pass` rule has the `alert`
keyword or not.
This patch fix corner-case scenarios of:
- accessing an index out of boundaries
- off-by-one access
Without changing how the engine increments the alerts.cnt, as this is
used in many places, and would be a more invasive change.
It checks the two different scenarios, plus the case when there is only
a single match as a silent `pass` rule.
Bug #8021
Bug #7630
Origin: upstream, https://github.com/OISF/suricata/commit/
5d6c24cc2ce6a390c0956b7ecb2c5efc47e72abc.patch
Bug: https://redmine.openinfosecfoundation.org/issues/8021
Subject: Upstream fix for CVE-2025-64330
Gbp-Pq: Name CVE-2025-64330.patch
} else if (PacketCheckAction(p, ACTION_DROP) && EngineModeIsIPS()) {
JB_SET_STRING(jb, "action", "drop");
- } else if (p->alerts.alerts[p->alerts.cnt].action & ACTION_PASS) {
+ } else if (p->alerts.cnt == 0 ||
+ (p->alerts.cnt <= packet_alert_max &&
+ (p->alerts.alerts[p->alerts.cnt - 1].action &
+ (ACTION_PASS | ACTION_ALERT)) == (ACTION_PASS | ACTION_ALERT)) ||
+ (p->alerts.cnt < packet_alert_max &&
+ p->alerts.alerts[p->alerts.cnt].action & ACTION_PASS)) {
JB_SET_STRING(jb, "action", "pass");
} else {
// TODO make sure we don't have a situation where this wouldn't work